#include "translate.h"
#include <sys/time.h>
#include <unistd.h>
#include <BFSTask.h>
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <TFrame.h>
#include <pppnode.h>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/breadth_first_search.hpp>
#include <boost/pending/indirect_cmp.hpp>
#include <boost/pending/integer_range.hpp>

using namespace boost;
template < typename TimeMap > class bfs_time_visitor:public default_bfs_visitor {
  typedef typename property_traits < TimeMap >::value_type T;
public:
  bfs_time_visitor(TimeMap tmap, T & t):m_timemap(tmap), m_time(t) { }
  template < typename Vertex, typename Graph >
    void discover_vertex(Vertex u, const Graph & g) const
  {
    put(m_timemap, u, m_time++);
  }
  TimeMap m_timemap;
  T & m_time;
};

int 
main(int argc, char *argv[]) {


    using namespace boost;
    int size_vertices = 100;
    timeval tim;
    double t1, t2;
    PPPGraph G; Graph_t BG;
    int opt;
    std::string infile = "";

    while ((opt = getopt(argc, argv, "s:i:")) != -1) {
        switch(opt) {
            case 's':
                size_vertices = atoi(optarg);
                break;
            case 'i':
                infile += optarg;
                break;
            default:
                fprintf(stderr, "Usage: %s [-s {size of vertices}] [-i {input file name}]", argv[0]);
                exit(EXIT_FAILURE);
        }
    }

    if (size_vertices == 0 || infile == "") {
        fprintf(stderr, "Usage: %s [-s {size of vertices}] [-i {input file name}]\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    buildGraph(infile, &G, size_vertices);
    //buildBoost(infile, &BG, size_vertices);

    WorkQueue * Q = new WorkQueue();
    Q->setNumThreads(8);
    Q->initThreads();
    BFSTask_t * bfs = new BFSTask_t( G, Q , size_vertices);
    //std::cout << "Initialization done \n";
    Q->addTask(bfs);
    Q->wait_for_threads();

#if 0
    std::vector < graph_traits < Graph_t >::vertex_descriptor >
        p(num_vertices(BG));

    // Typedefs
    typedef graph_traits < Graph_t >::vertex_descriptor Vertex;
    typedef graph_traits < Graph_t >::vertices_size_type Size;
    typedef Size* Iiter;

    // a vector to hold the discover time property for each vertex
    std::vector < Size > dtime(num_vertices(BG));

    Size time = 0;
    bfs_time_visitor < Size * >vis(&dtime[0], time);
    gettimeofday(&tim, NULL);
    t1=tim.tv_sec+(tim.tv_usec/1000000.0);
    breadth_first_search(BG, vertex(0, BG), visitor(vis));
    gettimeofday(&tim, NULL);
    t2=tim.tv_sec+(tim.tv_usec/1000000.0);	
    printf("%.6lf seconds elapsed\n", t2-t1);
    // Use std::sort to order the vertices by their discover time
    std::vector<graph_traits<Graph_t>::vertices_size_type > discover_order(size_vertices);
    integer_range < int >range(0, size_vertices);
    std::copy(range.begin(), range.end(), discover_order.begin());
    std::sort(discover_order.begin(), discover_order.end(),
            indirect_cmp < Iiter, std::less < Size > >(&dtime[0]));
#endif
#if 0
    std::cout << "order of discovery: ";
    for (int i = 0; i < size_vertices; ++i)
        std::cout << discover_order[i] << " ";
    std::cout << std::endl;
#endif

    /*
       for (int i = 0 ; i < size_vertices ; i++) {
       std::cout << i << " ----> " << p[i] << std::endl;
       }
     */
#if 0
    WorkQueue * Q = new WorkQueue();
    Q->setNumThreads(2);
    Q->initThreads();

    std::cout << "Main going to sleep\n";
    sleep(15);
#endif
    return EXIT_SUCCESS;
}
